﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "GcmpMathInterface.h"
#include "MathUtils.h"
#include "Vector3d.h"
#include "Matrix4dUtils.h"

namespace gcmp
{

    class Vector3f;
    class Vector3d;
    class Matrix4d;

    /// \brief Vector3d的工具类
    ///
    /// 
    class GCMP_MATH_INTERFACE_EXPORT Vector3dUtils
    {
    public:

        /// \brief   计算两个点的距离
        ///
        /// \param point1  点
        /// \param point2  另一个点
        /// \return  距离
        static double Distance(const Vector3d& point1, const Vector3d& point2);

        /// \brief   计算两个点的距离平方
        ///
        /// \param point1  点
        /// \param point2  另一个点
        /// \return  距离平方
        static double SqrDistance(const Vector3d& point1, const Vector3d& point2);

        /// \brief   判断点或向量是否在给定误差下相等
        ///
        /// \param vec1  向量
        /// \param vec2  另一向量
        /// \param epsilon 容差(默认Constants::DOUBLE_EPS)
        /// \return  true: 相等   false: 不等
        static bool IsEqual(const Vector3d& vec1, const Vector3d& vec2, double epsilon = Constants::DOUBLE_EPS);

        /// \brief   判断两个向量是否垂直
        ///
        /// \param vec1  向量
        /// \param vec2  另一向量
        /// \param epsilon  容差(默认Constants::DOUBLE_EPS)
        /// \return  true: 垂直   false: 不垂直
        static bool IsPerpendicular(const Vector3d& vec1, const Vector3d& vec2, double epsilon = Constants::DOUBLE_EPS);

        /// \brief   判断两个向量是否平行
        ///
        /// \param vec1  向量
        /// \param vec2  另一向量
        /// \param epsilon  容差(默认Constants::DOUBLE_EPS)
        /// \return  true: 平行   false: 不平行
        static bool IsParallel(const Vector3d& vec1, const Vector3d& vec2, const double epsilon = Constants::DOUBLE_EPS);

        /// \brief  返回绕空间任意轴旋转的点
        ///
        /// \param point   点
        /// \param basePt  基点
        /// \param dir     轴方向
        /// \param radian  旋转角度
        /// \return    绕空间任意轴旋转的点
        static Vector3d RotatePointAroundAxis(const Vector3d& point, const Vector3d& basePt, const Vector3d& dir, const double& radian);

        /// \brief   返回绕空间任意轴旋转的向量
        ///
        /// \param vec  向量
        /// \param dir  轴方向
        /// \param radian  旋转角度(弧度)
        /// \return   绕空间任意轴旋转的向量
        static Vector3d RotateVectorAroundAxis(const Vector3d& vec, const Vector3d& dir, const double& radian);

        /// \brief   对三维点进行矩阵变换
        ///
        /// \param pt  传入点
        /// \param mat  变换矩阵
        /// \return   变换后的点
        static Vector3d TransformPoint(const Vector3d& pt, const Matrix4d& mat);

        /// \brief   对三维向量进行矩阵变换
        ///
        /// \param vec  传入向量
        /// \param mat  变换矩阵
        /// \return   变换后的向量
        static Vector3d TransformVector(const Vector3d& vec, const Matrix4d& mat);

        /// \brief   计算给定向量逆时针转到该向量的转角,要求两个向量为单位向量
        ///
        /// \param vecUnitFrom  起始向量
        /// \param vecUnitTo  终止向量
        /// \param pNormal  缺省为空; 如赋值，则取向量vecFrom和vecTo所在平面的法向或负法向
        /// \return  弧度值 取值范围[0,PI]
        static double GetAngle(const Vector3d& vecUnitFrom, const Vector3d & vecUnitTo);

        /// \brief   计算给定向量逆时针转到该向量的转角,要求两个向量为单位向量
        ///
        /// \param vecUnitFrom  起始向量
        /// \param vecUnitTo  终止向量
        /// \param pNormal  缺省为空; 如赋值，则取向量vecFrom和vecTo所在平面的法向或负法向
        /// \return  弧度值  取值范围[0，2PI]
        static double GetAngle(const Vector3d& vecUnitFrom, const Vector3d & vecUnitTo, const Vector3d& normal);

     public:

         /// \brief   获取两个向量的夹角(锐角)，向量不考虑方向
         ///
         /// \param vec1  向量
         /// \param vec2  另一向量
         /// \return   夹角[0, PI/2]
         static double GetAcuteAngle(const Vector3d& vec1, const Vector3d& vec2);

        /// \brief   计算一个向量的任一垂直向量
        ///
        /// \param vec  向量
        /// \param perpendicularVec  垂直向量
        /// \param epsilon  容差(默认Constants::DOUBLE_EPS)
        /// \return  true: 垂直   false: 不垂直
         static bool AskPerpendicularVector(const Vector3d& vec, Vector3d& perpendicularVec, const double epsilon = Constants::DOUBLE_EPS);

        /// \brief    当前向量沿参考向量方向及其垂直向量分解
        ///
        /// \param vec   向量
        /// \param refVec   参考向量
        /// \param projVec  参考向量的分量
        /// \param projVertVec  与参考向量相垂直的分量
        /// \return  是否有效
         static bool Decompose(const Vector3d& vec, const Vector3d& refVec, Vector3d& projVec, Vector3d& projVertVec);

         static Vector3d ToVector3d(const Vector3f& vec);
    };
}


